﻿using System;
using System.Collections.Generic;
using System.Common.Lock;
using System.Controls.Base;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace System.Controls
{
  public class RadioGroup : ItemsControl, ISelectionOwner
  {
    public static readonly DependencyProperty CornerRadiusProperty =
      DependencyProperty.Register( "CornerRadius",
        typeof( CornerRadius ), typeof( RadioGroup ) );

    private readonly DeferSelection fDeferSelection;
    private readonly Suppressor fSelectedIndex = new Suppressor();
    private readonly Suppressor fSelectedItem = new Suppressor();

    static RadioGroup()
    {
      DefaultStyleKeyProperty.OverrideMetadata( typeof( RadioGroup ),
        new FrameworkPropertyMetadata( typeof( RadioGroup ) ) );
    }

    public RadioGroup()
    {
      fDeferSelection = new DeferSelection( this );
      ItemsPanel = GetDefaultItemsPanelTemplate();
    }

    public CornerRadius CornerRadius
    {
      get { return (CornerRadius)GetValue( CornerRadiusProperty ); }
      set { SetValue( CornerRadiusProperty, value ); }
    }

    public GeneratorStatus GetGeneratorStatus()
    {
      return ItemContainerGenerator.Status;
    }

    public int ItemsCount
    {
      get
      {
        return Items != null ? Items.Count : 0;
      }
    }

    public void SetSelectedIndex( int newIndex )
    {
      if ( fSelectedIndex.Suppressed )
        return;

      using ( fSelectedIndex.Suppress() )
      {
        if ( !fSelectedItem.Suppressed )
          Selection.SetSelectedItem( this, Items[newIndex] );

        UpdateChecked( newIndex );
      }
    }

    public void SetDeferred( object value, DeferredType dType )
    {
      fDeferSelection.SetDeferred( value, dType );
    }

    public void SetSelectedItem( object newValue )
    {
      if ( fSelectedItem.Suppressed )
        return;

      using ( fSelectedItem.Suppress() )
      {
        if ( !fSelectedIndex.Suppressed )
          Selection.SetSelectedIndex( this, Items.IndexOf( newValue ) );

        UpdateChecked( newValue );
      }
    }

    private void UpdateChecked( int index )
    {
      var container = ItemContainerGenerator.ContainerFromIndex( index ) as ToggleButton;
      if ( container != null && !( container.IsChecked ?? false ) )
        container.IsChecked = true;
    }

    private void UpdateChecked( object value )
    {
      var container = ItemContainerGenerator.ContainerFromItem( value ) as ToggleButton;
      if ( container != null && !( container.IsChecked ?? false ) )
        container.IsChecked = true;
    }

    private static ItemsPanelTemplate GetDefaultItemsPanelTemplate()
    {
      var template = new ItemsPanelTemplate( new FrameworkElementFactory( typeof( WrapPanel ) ) );
      template.Seal();
      return template;
    }

    protected override void OnSelectionChanged( object content )
    {
      Selection.SetSelectedItem( this, content );
    }



    #region Overrides of ItemsControl

    internal override void GeneratorStateChanged( GeneratorStatus status )
    {
      if ( status != GeneratorStatus.ContainersGenerated )
        return;

      if ( fDeferSelection.HasDeferredSelection )
      {
        fDeferSelection.UpdateDeferredSelection();
        return;
      }

      var index = Selection.GetSelectedIndex( this );

      if ( index != -1 )
      {
        UpdateChecked( index );
        return;
      }

      var item = Selection.GetSelectedItem( this );
      if ( item == null )
        return;

      UpdateChecked( item );
    }

    #endregion
  }
}
